// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 与时间相关的运行时和打包时间。

package runtime

import (
	"internal/abi"
	"runtime/internal/atomic"
	"runtime/internal/sys"
	"unsafe"
)

// 打包时间知道这个结构的布局。
// 如果此结构发生更改，请调整/时间/睡眠。开始：/runtimeTimer。
type timer struct {
	// 如果这个计时器在一个堆上，那么它在哪个P的堆上。
	// puintptr而不是*p，以匹配其他包中定义的此结构的版本
	// 中的uintptr。
	pp puintptr

	// 计时器在时间点唤醒，然后在时间+周期点唤醒。。。（仅限句点>0）
	// 每次在计时器goroutine中调用f（arg，now），因此f必须是
	// 一个性能良好的函数，而不是阻塞。
	// 
	// when在活动计时器上必须为正值。
	when   int64
	period int64
	f      func(any, uintptr)
	arg    any
	seq    uintptr

	// 在timerModifiedXX状态下设置when字段的内容。
	nextwhen int64

	// 状态字段包含以下值之一。
	status uint32
}

// 此文件之外的代码在使用计时器值时必须小心。
// 
// pp、status和nextwhen字段只能由此文件中的代码使用。
// 
// 创建新计时器值的代码可以设置时间、周期、f、
// arg和seq字段。
// 可以将新的计时器值传递给addtimer（由time.startTimer调用）。
// 这样做之后，任何字段都不能被触碰。
// 
// 活动计时器（已传递给addtimer的计时器）可能是
// 传递给deltimer（time.stopTimer），之后它不再是
// 活动计时器。它是一个非活动计时器。
// 在非活动计时器中，可以修改句点、f、arg和seq字段，但不能修改when字段。
// 可以删除一个不活动的计时器，让GC收集它。
// 将非活动计时器传递给addtimer是不正确的。
// 只能将新分配的计时器值传递给addtimer。
// 
// 可以将活动计时器传递给modtimer。不得触碰任何领域。
// 它仍然是一个活动计时器。
// 
// 可以将一个非活动计时器传递给resettimer，将其转换为一个
// 带有更新时间字段的活动计时器。
// 可以将新分配的计时器值传递给resettimer。
// 
// 计时器操作包括addtimer、deltimer、modtimer、resettimer、
// 清除计时器、调整计时器和运行计时器。
// 
// 我们不允许同时调用addtimer/deltimer/modtimer/resettimer，
// 但是可以同时调用AdjustTimer和runtimer。
// 
// 活动计时器位于计时器字段中与P相连的堆中。
// 不活跃的计时器也暂时住在那里，直到它们被移除。
// 
// addtimer:
// TimerStatus->timerWaiting 
// 其他任何东西->恐慌：无效值
// deltimer:
// timerWaiting->TimerModifing->TimerDetectedtimerModifying->timerDeleted 
// TimerStatus->do nothing 
// timerDeleted->do nothing 
// timerRemoving->do nothing 
// timerRemoved->do do nothing 
// timerRunning->等待状态更改
// timerMoving->等待状态更改
// timerModifying->wait to status changes 
// modtimer:
// timerModifying->timerModifying->TimerModifyed XX 
// TimerModifyed XX->timerModifying->timerModifying->timerModifying->timerModifying->timerModifying->
// timerMoving->wait TOR TOURE 
// timerRemoving->wait TOURE 
// TIMERMODIFING->
// cleantimers（在P的计时器堆中查找）：
// timerDeleted->timerRemoved->timerRemoved 
// timerModifiedXX->TimerMoveing->timerWaiting 
// adjusttimers（在P的计时器堆中查找）：
// timerRemoved->timerRemoved->timerRemoved->timerRemoved 
// timerModifiedXX->timerMoving->timerWaiting 
// runtimer（在P的计时器堆中查找）：
// TimerStatus->panic:未初始化的计时器
// timerWaiting->timerWaiting或
// timerWaiting->timerWaiting->timerRunning->TimerVanting或
// timerWaiting->timerWaiting->
// timerModifiedXX->TimerMoved->timerMoving 
// timerDeleted->timerRemoving->timerRemoved 
// timerRunning->panic:并发运行计时器调用
// timerRemoved->panic:不一致的计时器堆
// timerRemoving->panic:不一致的计时器堆
// timerMoving->panic:不一致的计时器堆

// 计时器状态字段的值。
const (
	// 计时器尚未设置状态。
	timerNoStatus = iota

	// 等待计时器启动。
	// 计时器在某个P堆中。
	timerWaiting

	// 运行计时器功能。
	// 计时器将仅短暂处于此状态。
	timerRunning

	// 计时器已删除，应删除。
	// 它不应该运行，但它仍然在一些P堆中。
	timerDeleted

	// 正在删除计时器。
	// 计时器将仅短暂处于此状态。
	timerRemoving

	// 计时器已停止。
	// 它不在任何P的堆中。
	timerRemoved

	// 正在修改计时器。
	// 计时器将仅短暂处于此状态。
	timerModifying

	// 计时器已修改为较早的时间。
	// 新的when值位于nextwhen字段中。
	// 计时器在某个P堆中，可能在错误的位置。
	timerModifiedEarlier

	// 计时器已修改为相同或更晚的时间。
	// 新的when值位于nextwhen字段中。
	// 计时器在某个P堆中，可能在错误的位置。
	timerModifiedLater

	// 计时器已被修改，正在移动。
	// 计时器将仅短暂处于此状态。
	timerMoving
)

// maxWhen是计时器的when字段的最大值。
const maxWhen = 1<<63 - 1

// 可以将verifyTimers设置为true，以添加调试检查，确保
// 计时器堆有效。
const verifyTimers = false

// 包时API。
// Godoc在打包时使用注释，而不是这些。时间。现在在汇编中实现。


// timeSleep使当前goroutine睡眠至少ns纳秒。
// go:linkname timeSleep time。Sleep 
func timeSleep(ns int64) {
	if ns <= 0 {
		return
	}

	gp := getg()
	t := gp.timer
	if t == nil {
		t = new(timer)
		gp.timer = t
	}
	t.f = goroutineReady
	t.arg = gp
	t.nextwhen = nanotime() + ns
	if t.nextwhen < 0 { // 检查溢出。
		t.nextwhen = maxWhen
	}
	gopark(resetForSleep, unsafe.Pointer(t), waitReasonSleep, traceEvGoSleep, 1)
}

// resetForSleep在goroutine停了timeSleep之后被调用。
// 我们不能在timeSleep中调用resettimer，因为如果这是一个短的
// 睡眠，并且有许多goroutine，那么在goroutine停止之前，P可以运行
// 计时器函数goroutineReady。
func resetForSleep(gp *g, ut unsafe.Pointer) bool {
	t := (*timer)(ut)
	resettimer(t, t.nextwhen)
	return true
}

// startTimer将t添加到计时器堆中。
// go:linkname开始时间。startTimer 
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

// stopTimer停止计时器。
// 它报告t在运行之前是否已停止。
// go:linkname停止计时器时间。stopTimer 
func stopTimer(t *timer) bool {
	return deltimer(t)
}

// resetTimer重置非活动计时器，将其添加到堆中。
// go:linkname重置计时器时间。resetTimer 
// 报告计时器在运行前是否已修改。
func resetTimer(t *timer, when int64) bool {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	return resettimer(t, when)
}

// modTimer修改现有计时器。
// go:linkname modTimer time。modTimer 
func modTimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq uintptr) {
	modtimer(t, when, period, f, arg, seq)
}

// Go运行时。

// 准备好goroutine arg。
func goroutineReady(arg any, seq uintptr) {
	goready(arg.(*g), 0)
}

// addtimer在当前的P中添加一个计时器。
// 这只能用新创建的计时器调用。
// 这避免了更改某些P堆中计时器的when字段的风险，
// 这可能会导致堆未排序。
func addtimer(t *timer) {
	// 何时必须为正。负值将导致runtimer在其增量计算期间溢出，并且不会使其他运行时
	// 计时器过期。零将导致checktimer无法注意到计时器。
	if t.when <= 0 {
		throw("timer when must be positive")
	}
	if t.period < 0 {
		throw("timer period must be non-negative")
	}
	if t.status != timerNoStatus {
		throw("addtimer called with initialized timer")
	}
	t.status = timerWaiting

	when := t.when

	// 在使用pp时禁用抢占，以避免更改另一个P的堆。
	mp := acquirem()

	pp := getg().m.p.ptr()
	lock(&pp.timersLock)
	cleantimers(pp)
	doaddtimer(pp, t)
	unlock(&pp.timersLock)

	wakeNetPoller(when)

	releasem(mp)
}

// doaddtimer将t添加到当前P的堆中。
// 调用者必须已锁定pp的计时器。
func doaddtimer(pp *p, t *timer) {
	// 计时器依赖于网络轮询器，因此请确保轮询器
	// 已启动。
	if netpollInited == 0 {
		netpollGenericInit()
	}

	if t.pp != 0 {
		throw("doaddtimer: P already set in timer")
	}
	t.pp.set(pp)
	i := len(pp.timers)
	pp.timers = append(pp.timers, t)
	siftupTimer(pp.timers, i)
	if t == pp.timers[0] {
		atomic.Store64(&pp.timer0When, uint64(t.when))
	}
	atomic.Xadd(&pp.numTimers, 1)
}

// deltimer删除计时器t。它可能在其他P上，因此我们不能从计时器堆中实际删除它。我们只能将其标记为已删除。
// 它将在适当的时候被其所在堆的P删除。
// 报告计时器在运行前是否已删除。
func deltimer(t *timer) bool {
	for {
		switch s := atomic.Load(&t.status); s {
		case timerWaiting, timerModifiedLater:
			// 在计时器进行时间修改时防止抢占。
			// 这可能会导致自我僵局。见#38070。
			mp := acquirem()
			if atomic.Cas(&t.status, s, timerModifying) {
				// 必须在更改状态之前获取t.pp，
				// 作为另一个goroutine中的CleanTimer 
				// 可以清除t.pp中的timerDeleted计时器。
				tpp := t.pp.ptr()
				if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
					badTimer()
				}
				releasem(mp)
				atomic.Xadd(&tpp.deletedTimers, 1)
				// 计时器尚未运行。
				return true
			} else {
				releasem(mp)
			}
		case timerModifiedEarlier:
			// 在计时器进行时间调整时防止抢占。
			// 这可能会导致自我僵局。见#38070。
			mp := acquirem()
			if atomic.Cas(&t.status, s, timerModifying) {
				// 在将状态
				// 设置为timerDeleted之前，必须先获取t.pp。
				tpp := t.pp.ptr()
				if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
					badTimer()
				}
				releasem(mp)
				atomic.Xadd(&tpp.deletedTimers, 1)
				// 计时器尚未运行。
				return true
			} else {
				releasem(mp)
			}
		case timerDeleted, timerRemoving, timerRemoved:
			// 计时器已运行。
			return false
		case timerRunning, timerMoving:
			// 计时器正在运行或移动，由另一个P执行。
			// 等待计时器完成。
			osyield()
		case timerNoStatus:
			// 删除从未添加的计时器或
			// 已运行。另见第21874期。cun chu defg
			return false
		case timerModifying:
			// 等待另一个呼叫完成。
			osyield()
		default:
			badTimer()
		}
	}
}

// dodeltimer从当前P的堆中删除计时器i。
// 调用时，我们锁定在P上。
// 返回pp.timer中最小的更改索引。
// 调用者必须已锁定pp的计时器。
func dodeltimer(pp *p, i int) int {
	if t := pp.timers[i]; t.pp.ptr() != pp {
		throw("dodeltimer: wrong P")
	} else {
		t.pp = 0
	}
	last := len(pp.timers) - 1
	if i != last {
		pp.timers[i] = pp.timers[last]
	}
	pp.timers[last] = nil
	pp.timers = pp.timers[:last]
	smallestChanged := i
	if i != last {
		// 移动到我可能已将最后一个计时器移动到新的父级，
		// 所以请进行筛选以保留堆保证。
		smallestChanged = siftupTimer(pp.timers, i)
		siftdownTimer(pp.timers, i)
	}
	if i == 0 {
		updateTimer0When(pp)
	}
	atomic.Xadd(&pp.numTimers, -1)
	return smallestChanged
}

// dodeltimer0从当前P的堆中删除计时器0。
// 调用时，我们锁定在P上。
// 它会报告是否由于种族原因没有发现任何问题。
// 调用者必须已锁定pp的计时器。
func dodeltimer0(pp *p) {
	if t := pp.timers[0]; t.pp.ptr() != pp {
		throw("dodeltimer0: wrong P")
	} else {
		t.pp = 0
	}
	last := len(pp.timers) - 1
	if last > 0 {
		pp.timers[0] = pp.timers[last]
	}
	pp.timers[last] = nil
	pp.timers = pp.timers[:last]
	if last > 0 {
		siftdownTimer(pp.timers, 0)
	}
	updateTimer0When(pp)
	atomic.Xadd(&pp.numTimers, -1)
}

// modtimer修改现有计时器。
// 这由netpoll代码或时间调用。股票行情。重置或计时。计时器。重置。
// 报告计时器在运行前是否已修改。
func modtimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq uintptr) bool {
	if when <= 0 {
		throw("timer when must be positive")
	}
	if period < 0 {
		throw("timer period must be non-negative")
	}

	status := uint32(timerNoStatus)
	wasRemoved := false
	var pending bool
	var mp *m
loop:
	for {
		switch status = atomic.Load(&t.status); status {
		case timerWaiting, timerModifiedEarlier, timerModifiedLater:
			// 在计时器进行时间修改时防止抢占。
			// 这可能会导致自身死锁。见#38070。
			mp = acquirem()
			if atomic.Cas(&t.status, status, timerModifying) {
				pending = true // 计时器尚未运行
				break loop
			}
			releasem(mp)
		case timerNoStatus, timerRemoved:
			// 在计时器进行计时器修改时防止抢占。
			// 这可能会导致自我僵局。见#38070。
			mp = acquirem()

			// 计时器已运行，t不再在堆中。
			// 像addtimer一样行事。
			if atomic.Cas(&t.status, status, timerModifying) {
				wasRemoved = true
				pending = false // 计时器已运行或已停止
				break loop
			}
			releasem(mp)
		case timerDeleted:
			// 在计时器进行计时器修改时防止抢占。
			// 这可能会导致自我僵局。见#38070。
			mp = acquirem()
			if atomic.Cas(&t.status, status, timerModifying) {
				atomic.Xadd(&t.pp.ptr().deletedTimers, -1)
				pending = false // 计时器已停止
				break loop
			}
			releasem(mp)
		case timerRunning, timerRemoving, timerMoving:
			// 计时器正在运行或被另一个P移动。
			// 等待它完成。
			osyield()
		case timerModifying:
			// 多次同时调用modtimer。
			// 等待另一个呼叫完成。
			osyield()
		default:
			badTimer()
		}
	}

	t.period = period
	t.f = f
	t.arg = arg
	t.seq = seq

	if wasRemoved {
		t.when = when
		pp := getg().m.p.ptr()
		lock(&pp.timersLock)
		doaddtimer(pp, t)
		unlock(&pp.timersLock)
		if !atomic.Cas(&t.status, timerModifying, timerWaiting) {
			badTimer()
		}
		releasem(mp)
		wakeNetPoller(when)
	} else {
		// 计时器在其他P的堆中，因此我们无法更改
		// 时间字段。如果我们这样做了，另一个P的堆将发生故障。因此，我们将新的when值放在
		// nextwhen字段中，让另一个P在准备诉诸堆时设置when字段
		// 。
		t.nextwhen = when

		newStatus := uint32(timerModifiedLater)
		if when < t.when {
			newStatus = timerModifiedEarlier
		}

		tpp := t.pp.ptr()

		if newStatus == timerModifiedEarlier {
			updateTimerModifiedEarliest(tpp, when)
		}

		// 设置计时器的新状态。
		if !atomic.Cas(&t.status, timerModifying, newStatus) {
			badTimer()
		}
		releasem(mp)

		// 如果新状态更早，请叫醒投票人。
		if newStatus == timerModifiedEarlier {
			wakeNetPoller(when)
		}
	}

	return pending
}

// resettimer重置计时器应触发的时间。
// 如果用于非活动计时器，计时器将变为活动。
// 如果之前使用过或可能使用过计时器值，则应调用此函数而不是addtimer。
// 报告计时器在运行前是否已修改。
func resettimer(t *timer, when int64) bool {
	return modtimer(t, when, t.period, t.f, t.arg, t.seq)
}

// cleantimers清除计时器队列的头。这将加速
// 创建和删除计时器的程序；将它们留在堆中
// 会降低addtimer的速度。报告是否未发现计时器问题。
// 调用者必须为pp锁定了计时器。
func cleantimers(pp *p) {
	gp := getg()
	for {
		if len(pp.timers) == 0 {
			return
		}

		// 这个循环理论上可以运行一段时间，因为
		// 它持有timersLock，所以不能被抢占。
		// 如果有人试图抢先我们，就回来吧。
		// 我们可以稍后清理计时器。
		if gp.preemptStop {
			return
		}

		t := pp.timers[0]
		if t.pp.ptr() != pp {
			throw("cleantimers: bad p")
		}
		switch s := atomic.Load(&t.status); s {
		case timerDeleted:
			if !atomic.Cas(&t.status, s, timerRemoving) {
				continue
			}
			dodeltimer0(pp)
			if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
				badTimer()
			}
			atomic.Xadd(&pp.deletedTimers, -1)
		case timerModifiedEarlier, timerModifiedLater:
			if !atomic.Cas(&t.status, s, timerMoving) {
				continue
			}
			// 现在我们可以更改when字段。
			t.when = t.nextwhen
			// 将t移到正确的位置。
			dodeltimer0(pp)
			doaddtimer(pp, t)
			if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
				badTimer()
			}
		default:
			// 计时头不需要调整。
			return
		}
	}
}

// moveTimers将计时器的一个片段移动到pp。该片段已从另一个P获取
// 
// 当前在世界停止时调用，但调用方
// 预计已锁定pp的计时器。
func moveTimers(pp *p, timers []*timer) {
	for _, t := range timers {
	loop:
		for {
			switch s := atomic.Load(&t.status); s {
			case timerWaiting:
				if !atomic.Cas(&t.status, s, timerMoving) {
					continue
				}
				t.pp = 0
				doaddtimer(pp, t)
				if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
					badTimer()
				}
				break loop
			case timerModifiedEarlier, timerModifiedLater:
				if !atomic.Cas(&t.status, s, timerMoving) {
					continue
				}
				t.when = t.nextwhen
				t.pp = 0
				doaddtimer(pp, t)
				if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
					badTimer()
				}
				break loop
			case timerDeleted:
				if !atomic.Cas(&t.status, s, timerRemoved) {
					continue
				}
				t.pp = 0
				// 我们不再需要堆中的这个计时器。
				break loop
			case timerModifying:
				// 循环，直到修改完成。
				osyield()
			case timerNoStatus, timerRemoved:
				// 我们不应该在计时器堆中看到这些状态值。
				badTimer()
			case timerRunning, timerRemoving, timerMoving:
				// 其他一些P认为它拥有这个计时器，
				// 这不应该发生。
				badTimer()
			default:
				badTimer()
			}
		}
	}
}

// adjusttimers查看当前P堆中的计时器，查找
// 任何已修改为更早运行的计时器，并将它们放在
// 堆中正确的位置。在查找这些计时器时，它还会移动已修改为以后运行的计时器，并删除已删除的计时器。调用者必须已经锁定了pp.
func adjusttimers(pp *p, now int64) {
	// 的计时器。如果我们还没有到达第一次的时间，请不要做任何事情。这加快了调整
	// 大量计时器的程序，如果计时器很少过期的话。
	// 我们将推迟查看所有调整后的计时器，直到
	// 一个计时器实际过期。
	first := atomic.Load64(&pp.timerModifiedEarliest)
	if first == 0 || int64(first) > now {
		if verifyTimers {
			verifyTimerHeap(pp)
		}
		return
	}

	// 我们将清除所有时间修改的早期计时器。
	atomic.Store64(&pp.timerModifiedEarliest, 0)

	var moved []*timer
	for i := 0; i < len(pp.timers); i++ {
		t := pp.timers[i]
		if t.pp.ptr() != pp {
			throw("adjusttimers: bad p")
		}
		switch s := atomic.Load(&t.status); s {
		case timerDeleted:
			if atomic.Cas(&t.status, s, timerRemoving) {
				changed := dodeltimer(pp, i)
				if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
					badTimer()
				}
				atomic.Xadd(&pp.deletedTimers, -1)
				// 返回最早更改的堆条目。
				// /“-1”，因为循环将添加1。
				i = changed - 1
			}
		case timerModifiedEarlier, timerModifiedLater:
			if atomic.Cas(&t.status, s, timerMoving) {
				// 现在我们可以更改when字段。
				t.when = t.nextwhen
				// 把t从堆上拿下来，抓住它。
				// 我们还没有添加回去，因为
				// 堆操作可能会导致我们的
				// 循环跳过其他计时器。
				changed := dodeltimer(pp, i)
				moved = append(moved, t)
				// 返回最早更改的堆条目。
				// /“-1”，因为循环将添加1。
				i = changed - 1
			}
		case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving:
			badTimer()
		case timerWaiting:
			// 好的，没什么可做的。
		case timerModifying:
			// 修改完成后再次检查。
			osyield()
			i--
		default:
			badTimer()
		}
	}

	if len(moved) > 0 {
		addAdjustedTimers(pp, moved)
	}

	if verifyTimers {
		verifyTimerHeap(pp)
	}
}

// addAdjustedTimers将我们在adjusttimers 
// 中调整的所有计时器添加回计时器堆。
func addAdjustedTimers(pp *p, moved []*timer) {
	for _, t := range moved {
		doaddtimer(pp, t)
		if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
			badTimer()
		}
	}
}

// nobarrierWakeTime查看P的计时器并返回我们应该唤醒netpoller的时间。如果没有计时器，则返回0。
// 此函数在删除P时调用，必须在没有任何写障碍的情况下运行。
// go:nowritebarrierrec 
func nobarrierWakeTime(pp *p) int64 {
	next := int64(atomic.Load64(&pp.timer0When))
	nextAdj := int64(atomic.Load64(&pp.timerModifiedEarliest))
	if next == 0 || (nextAdj != 0 && nextAdj < next) {
		next = nextAdj
	}
	return next
}

// runtimer检查计时器中的第一个计时器。如果基于now准备就绪，则
// 它运行计时器并删除或更新它。
// 如果它运行了计时器，则返回0；如果没有更多计时器，则返回1；如果没有更多计时器，则返回时间
// 第一个计时器应该运行的时间。
// 调用者必须已锁定pp的计时器。
// 如果计时器正在运行，这将临时解锁计时器。
// 开始：系统堆栈
func runtimer(pp *p, now int64) int64 {
	for {
		t := pp.timers[0]
		if t.pp.ptr() != pp {
			throw("runtimer: bad p")
		}
		switch s := atomic.Load(&t.status); s {
		case timerWaiting:
			if t.when > now {
				// 未准备好运行。
				return t.when
			}

			if !atomic.Cas(&t.status, s, timerRunning) {
				continue
			}
			// 注意RunonItemer可能会临时解锁
			// pp.timersLock。
			runOneTimer(pp, t, now)
			return 0

		case timerDeleted:
			if !atomic.Cas(&t.status, s, timerRemoving) {
				continue
			}
			dodeltimer0(pp)
			if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
				badTimer()
			}
			atomic.Xadd(&pp.deletedTimers, -1)
			if len(pp.timers) == 0 {
				return -1
			}

		case timerModifiedEarlier, timerModifiedLater:
			if !atomic.Cas(&t.status, s, timerMoving) {
				continue
			}
			t.when = t.nextwhen
			dodeltimer0(pp)
			doaddtimer(pp, t)
			if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
				badTimer()
			}

		case timerModifying:
			// 等待修改完成。
			osyield()

		case timerNoStatus, timerRemoved:
			// 不应在堆上看到新的或不活动的计时器。
			badTimer()
		case timerRunning, timerRemoving, timerMoving:
			// 只有当定时器被锁定时才应该设置，而我们没有这样做。
			badTimer()
		default:
			badTimer()
		}
	}
}

// RunonNetimer只运行一个计时器。
// 调用者必须已锁定pp的计时器。
// 这将在运行计时器功能时临时解锁计时器。
// go:systemstack 
func runOneTimer(pp *p, t *timer, now int64) {
	if raceenabled {
		ppcur := getg().m.p.ptr()
		if ppcur.timerRaceCtx == 0 {
			ppcur.timerRaceCtx = racegostart(abi.FuncPCABIInternal(runtimer) + sys.PCQuantum)
		}
		raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t))
	}

	f := t.f
	arg := t.arg
	seq := t.seq

	if t.period > 0 {
		// 留在堆中，但在下次点火时进行调整。
		delta := t.when - now
		t.when += t.period * (1 + -delta/t.period)
		if t.when < 0 { // 检查溢出。
			t.when = maxWhen
		}
		siftdownTimer(pp.timers, 0)
		if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
			badTimer()
		}
		updateTimer0When(pp)
	} else {
		// 从堆中删除。
		dodeltimer0(pp)
		if !atomic.Cas(&t.status, timerRunning, timerNoStatus) {
			badTimer()
		}
	}

	if raceenabled {
		// 暂时使用当前P的racectx进行g0。
		gp := getg()
		if gp.racectx != 0 {
			throw("runOneTimer: unexpected racectx")
		}
		gp.racectx = gp.m.p.ptr().timerRaceCtx
	}

	unlock(&pp.timersLock)

	f(arg, seq)

	lock(&pp.timersLock)

	if raceenabled {
		gp := getg()
		gp.racectx = 0
	}
}

// clearDeletedTimers从P的计时器堆中删除所有已删除的计时器。
// 如果程序
// 启动许多长时间运行的计时器，然后停止它们，则此选项用于避免阻塞堆。
// 例如，这可以通过上下文实现。超时。
// 
// 这是唯一一个遍历整个计时器堆的函数，而不是只在世界停止时运行的移动计时器。
// 
// 调用者必须已锁定pp的计时器。
func clearDeletedTimers(pp *p) {
	// 我们将清除所有时间修改的早期计时器。
	// 现在就这样做，以防在我们循环时出现新的循环。
	atomic.Store64(&pp.timerModifiedEarliest, 0)

	cdel := int32(0)
	to := 0
	changedHeap := false
	timers := pp.timers
nextTimer:
	for _, t := range timers {
		for {
			switch s := atomic.Load(&t.status); s {
			case timerWaiting:
				if changedHeap {
					timers[to] = t
					siftupTimer(timers, to)
				}
				to++
				continue nextTimer
			case timerModifiedEarlier, timerModifiedLater:
				if atomic.Cas(&t.status, s, timerMoving) {
					t.when = t.nextwhen
					timers[to] = t
					siftupTimer(timers, to)
					to++
					changedHeap = true
					if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
						badTimer()
					}
					continue nextTimer
				}
			case timerDeleted:
				if atomic.Cas(&t.status, s, timerRemoving) {
					t.pp = 0
					cdel++
					if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
						badTimer()
					}
					changedHeap = true
					continue nextTimer
				}
			case timerModifying:
				// 循环，直到修改完成。
				osyield()
			case timerNoStatus, timerRemoved:
				// 我们不应该在计时器堆中看到这些状态值。
				badTimer()
			case timerRunning, timerRemoving, timerMoving:
				// 其他一些P认为它拥有这个计时器，
				// 这不应该发生。
				badTimer()
			default:
				badTimer()
			}
		}
	}

	// 将计时器片中的剩余插槽设置为零，
	// 以便可以对计时器值进行垃圾收集。
	for i := to; i < len(timers); i++ {
		timers[i] = nil
	}

	atomic.Xadd(&pp.deletedTimers, -cdel)
	atomic.Xadd(&pp.numTimers, -cdel)

	timers = timers[:to]
	pp.timers = timers
	updateTimer0When(pp)

	if verifyTimers {
		verifyTimerHeap(pp)
	}
}

// verifyTimerHeap验证计时器堆是否处于有效状态。
// 这仅用于调试，仅在verifyTimers为true时调用。
// 呼叫方必须已锁定计时器。
func verifyTimerHeap(pp *p) {
	for i, t := range pp.timers {
		if i == 0 {
			// 第一个计时器没有父对象。
			continue
		}

		// 堆是四元的。请参阅siftupTimer和siftdownTimer。
		p := (i - 1) / 4
		if t.when < pp.timers[p].when {
			print("bad timer heap at ", i, ": ", p, ": ", pp.timers[p].when, ", ", i, ": ", t.when, "\n")
			throw("bad timer heap")
		}
	}
	if numTimers := int(atomic.Load(&pp.numTimers)); len(pp.timers) != numTimers {
		println("timer heap len", len(pp.timers), "!= numTimers", numTimers)
		throw("bad timer heap len")
	}
}

// updateTimer0When设置P的timer0When字段。
// 调用者必须已锁定pp的计时器。
func updateTimer0When(pp *p) {
	if len(pp.timers) == 0 {
		atomic.Store64(&pp.timer0When, 0)
	} else {
		atomic.Store64(&pp.timer0When, uint64(pp.timers[0].when))
	}
}

// UpdateTimeModifiedDearest更新
// Previous TimerModifiedArier值的记录的nextwhen字段。
// pp的计时器将不会被锁定。
func updateTimerModifiedEarliest(pp *p, nextwhen int64) {
	for {
		old := atomic.Load64(&pp.timerModifiedEarliest)
		if old != 0 && int64(old) < nextwhen {
			return
		}
		if atomic.Cas64(&pp.timerModifiedEarliest, old, uint64(nextwhen)) {
			return
		}
	}
}

// timeSleepUntil返回下一个计时器应该启动的时间，以及保存该计时器所在的计时器堆的P。
// 这只由sysmon和checkdead调用。
func timeSleepUntil() (int64, *p) {
	next := int64(maxWhen)
	var pret *p

	// 防止所有P切片更改。这就像是重夺。
	lock(&allpLock)
	for _, pp := range allp {
		if pp == nil {
			// 如果procresize增长了
			// allp但尚未创建新的Ps，则可能发生这种情况。
			continue
		}

		w := int64(atomic.Load64(&pp.timer0When))
		if w != 0 && w < next {
			next = w
			pret = pp
		}

		w = int64(atomic.Load64(&pp.timerModifiedEarliest))
		if w != 0 && w < next {
			next = w
			pret = pp
		}
	}
	unlock(&allpLock)

	return next, pret
}

// 堆维护算法。
// 这些算法手动检查切片索引错误。
// 如果程序使用racy 
// 访问计时器，可能会发生切片索引错误。我们不想在这里惊慌失措，因为它会导致程序崩溃，并显示一条神秘的消息“惊慌持有锁”。相反，我们惊慌失措，而不是拿着锁。

// siftupTimer通过将计时器向上移动到堆的顶部，将计时器放置在堆中正确的位置i。
// 返回最小的修改索引。
func siftupTimer(t []*timer, i int) int {
	if i >= len(t) {
		badTimer()
	}
	when := t[i].when
	if when <= 0 {
		badTimer()
	}
	tmp := t[i]
	for i > 0 {
		p := (i - 1) / 4 // 父
		if when >= t[p].when {
			break
		}
		t[i] = t[p]
		i = p
	}
	if tmp != t[i] {
		t[i] = tmp
	}
	return i
}

// siftdownTimer将计时器向下移动到堆的底部，将其放置在堆中正确位置的位置i。
func siftdownTimer(t []*timer, i int) {
	n := len(t)
	if i >= n {
		badTimer()
	}
	when := t[i].when
	if when <= 0 {
		badTimer()
	}
	tmp := t[i]
	for {
		c := i*4 + 1 // 左子
		c3 := c + 2  // 中子
		if c >= n {
			break
		}
		w := t[c].when
		if c+1 < n && t[c+1].when < w {
			w = t[c+1].when
			c++
		}
		if c3 < n {
			w3 := t[c3].when
			if c3+1 < n && t[c3+1].when < w3 {
				w3 = t[c3+1].when
				c3++
			}
			if w3 < w {
				w = w3
				c = c3
			}
		}
		if w >= when {
			break
		}
		t[i] = t[c]
		i = c
	}
	if tmp != t[i] {
		t[i] = tmp
	}
}

// 如果计时器数据结构已损坏，则调用badTimer，
// 可能是由于程序的快速使用。我们在这里恐慌，而不是
// 因为持有锁时无效的片访问而恐慌。
// 见第25686期。
func badTimer() {
	throw("timer data corruption")
}
